package cn.janus.component;

import cn.hutool.core.collection.CollUtil;
import cn.janus.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class JwtServerSecurityContextRepository implements ServerSecurityContextRepository {
    @DubboReference
    private UserService userService;

    @Override
    public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
        System.out.println("JwtServerSecurityContextRepository save");
        return null;
    }

    @Override
    public Mono<SecurityContext> load(ServerWebExchange exchange) {
        List<String> authorization = exchange.getRequest().getHeaders().get("Authorization");
        SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
        if (!CollUtil.isEmpty(authorization)) {
            String token = authorization.get(0);
            token = token.replace("Bearer", "");
            Map<String, Object> userInfo = userService.JwtBody(token);
            Object role = userInfo.get("roles");
            if (role instanceof List<?>) {
                List<?> list = (List<?>) role;
                List<SimpleGrantedAuthority> roles = list.stream()
                        .map(item -> item instanceof String ? new SimpleGrantedAuthority((String) item) : null)
                        .collect(Collectors.toList());
                String userId = (String) userInfo.get("subject");

                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(userId, null, roles);
                securityContext.setAuthentication(authentication);
            }
            return Mono.just(securityContext);
        }
        return Mono.just(SecurityContextHolder.getContext());
    }
}
